////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    TripleToucanGuts.cpp                                         //
//  Developer:   Marilyn Bolanos                                              //
//  Create date: 09/11/2007                                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: This is the class implementation for the slot gut of the     //
//               Australian Slot machine called TripleToucan.                 //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        Copyright (c) 2007 - Realtime Gaming.  All rights reserved.         //
////////////////////////////////////////////////////////////////////////////////

#include "TripleToucanGuts.h"

////////////////////////////////////////////////////////////////////////////
/// TripleToucanGuts::m_aLineWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by wheel icon and then count.  So to get the
/// SpinResult for 5 Aces, use the following code snippet:
///
///		SpinResult result = m_aLineWinSpinResults[ ICON_ACE ][ 5 ];
///
/// In this example result would be set to EVT_FIVE_ACE.
////////////////////////////////////////////////////////////////////////////
TripleToucanGuts::SpinResult TripleToucanGuts::m_aLineWinSpinResults[][6] = 
{
// Number of icons:			0			1					2						3						4						    5
/* ICON_NINE */			{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_THREE_NINE,			EVT_FOUR_NINE,		    EVT_FIVE_NINE			},
/* ICON_TEN */			{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_THREE_TEN,		    EVT_FOUR_TEN,		    EVT_FIVE_TEN			},
/* ICON_JACK */			{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_THREE_JACK,			EVT_FOUR_JACK,		    EVT_FIVE_JACK			},
/* ICON_QUEEN */		{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_THREE_QUEEN,		EVT_FOUR_QUEEN,		    EVT_FIVE_QUEEN			},
/* ICON_KING */			{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_THREE_KING,			EVT_FOUR_KING,		    EVT_FIVE_KING			},
/* ICON_ACE */			{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_THREE_ACE,			EVT_FOUR_ACE,		    EVT_FIVE_ACE			},
/* ICON_COCONUT */		{	EVT_LOSER,	EVT_LOSER,			EVT_TWO_COCONUT,        EVT_THREE_COCONUT,		EVT_FOUR_COCONUT,		EVT_FIVE_COCONUT	    },
/* ICON_FRANGAPANNI */	{	EVT_LOSER,	EVT_LOSER,			EVT_TWO_FRANGAPANNI,	EVT_THREE_FRANGAPANNI,  EVT_FOUR_FRANGAPANNI,	EVT_FIVE_FRANGAPANNI	},
/* ICON_FROG */		    {	EVT_LOSER,	EVT_LOSER,			EVT_TWO_FROG,			EVT_THREE_FROG,			EVT_FOUR_FROG,	        EVT_FIVE_FROG			},
/* ICON_PARROT */		{	EVT_LOSER,	EVT_LOSER,	        EVT_TWO_PARROT,         EVT_THREE_PARROT,	    EVT_FOUR_PARROT,	    EVT_FIVE_PARROT		    },
/* ICON_TOUCAN */		{	EVT_LOSER,	EVT_ONE_TOUCAN,		EVT_LOSER,				EVT_LOSER,			    EVT_LOSER,		        EVT_LOSER			    },
/* ICON_FRUITS */		{	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_LOSER,				EVT_LOSER,		        EVT_LOSER			    }
};



////////////////////////////////////////////////////////////////////////////
/// TripleToucanGuts::m_aScatterWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by icon count only, since flags are the only
/// scatter win.  So to get the SpinResult for 5 flags, use the
/// following code snippet:
///
///		SpinResult result = m_aScatterWinSpinResults[ 5 ];
///
/// In this example result would be set to EVT_FIVE_FLAG.
////////////////////////////////////////////////////////////////////////////
TripleToucanGuts::SpinResult TripleToucanGuts::m_aScatterWinSpinResults[6] = 
{
	// ICON_FLAG            Number of Icons
	EVT_LOSER,			    // 0
	EVT_LOSER,	            // 1
	EVT_TWO_FRUITS,	        // 2
	EVT_THREE_FRUITS,	    // 3
	EVT_FOUR_FRUITS,	    // 4
	EVT_FIVE_FRUITS 	    // 5
};

////////////////////////////////////////////////////////////////////////////
/// @fn 	 TripleToucanGuts::TripleToucanGuts()   
///
/// This is the default constructor for the class.
////////////////////////////////////////////////////////////////////////////
TripleToucanGuts::TripleToucanGuts()
{
	// If this doesn't compile it means that someone probably added
	// another icon type but did not update the
	// m_aLineWinSpinResults array. 
	C_ASSERT( countof( m_aLineWinSpinResults ) == NUM_VALID_ICONS );

    m_bAllowToucanIconSubstitutions = false;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 TripleToucanGuts::~TripleToucanGuts()
///
/// Destructor for TripleToucanGuts. 
////////////////////////////////////////////////////////////////////////////
TripleToucanGuts::~TripleToucanGuts()
{
    deallocateToucanSubstitutionIcons();
}



/********************************************************************************************************
@fn         TripleToucanGuts::load
@brief      Override of the SlotGuts::load framework function.
            Allocates our map of substitution icons for use in the free spin mode.
********************************************************************************************************/
bool8 
TripleToucanGuts::load(Info *info)
{
	// do base class load, and take the opportunity now to 
	// load up the substiution icons,
    return super::load( info ) && allocateToucanSubstitionIcons();
}


/********************************************************************************************************
@fn         TripleToucanGuts::allocateToucanSubstitionIcons
@brief      Go through each reel for free spin mode and make copies of the icons that could get 
            substituted, change them so they LOOK like toucan and add them to the map of substitution 
            icons.
@return	    true  
@param	    none
********************************************************************************************************/
bool8 TripleToucanGuts::allocateToucanSubstitionIcons()
{
    const SlotReel * pReel = NULL;

    uint8 gamemodeid = MODE_FREE_SPIN;

	
	// It works out that there are only toucan on reels 0, 2, and 4
	for( uint8 reel = 0 ; reel < getReelCount() ; reel += 2 )
	{
		pReel = getSlotReel( gamemodeid, reel );
		
		for( SlotReel::const_iterator begin( pReel->begin() ), current( pReel->begin() ), end( pReel->end() );
		current != end;
		++current )
		{
			if ( (*current)->iconid == ICON_TOUCAN )
			{
				//Map the previous one or two icons to a substitution icon
				if( distance (begin, current) >  1 )
				{
					// Copy & map the previous icon
					SlotReel::const_iterator previous = current - 1;
					
					addSubstitutionIcon( *previous );
					
					// And the previous one, too, if there's one there
					if ( distance( begin, previous ) > 2 )
					{
						addSubstitutionIcon( *--previous );
						
					}
				}
				
				//Map the next one or two icons to a substitution icon
				if ( distance( current, end ) > 1 )
				{                         
					// Copy & map the next icon
					SlotReel::const_iterator next = current + 1;
					
					addSubstitutionIcon( *next );
					
					if( distance( current, end ) > 2 )
					{
						addSubstitutionIcon( *++next );
					}
				}
			}
		}
	}
	
	return true;
}


/********************************************************************************************************
@fn         TripleToucanGuts::deallocateToucanSubstitutionIcons
@brief      Clean up our substitution map.
@return	    void      
@param	    none
********************************************************************************************************/
void TripleToucanGuts::deallocateToucanSubstitutionIcons()
{	

    for( SlotIconSubstitutionMap::iterator current( m_mapSubstitutionIcons.begin() ), end( m_mapSubstitutionIcons.end() );
            current != end;
            ++current )
            {
                delete current->second;
            }
}


/********************************************************************************************************
@fn         TripleToucanGuts::addSubstitutionIcon
@brief	    Adds an icon duplicating the passed icon, except with the iconid set to ICON_TOUCAN, for use 
            in the getIcon() method.
@return	    void  
@param	    const SlotIcon* icon - the icon to copy and key against in the new mapping.
********************************************************************************************************/
void  TripleToucanGuts::addSubstitutionIcon( const SlotIcon* icon)
{
    // Map this icon to a substitution icon
    // Copy the supplied icon
    SlotIcon* subicon = new SlotIcon( *icon );

    // Fix up its iconid
    subicon->iconid = ICON_TOUCAN;
    
    // Map it back to the real iterator for later.
    VERIFY( m_mapSubstitutionIcons.insert( make_pair( icon, subicon ) ).second );
}



/********************************************************************************************************
@fn         TripleToucanGuts::getIcon
@brief	    Override the base version to return the SlotIcon for the specified gamemode, reel and position.
            If we are in free spin mode and any icon on the visible reel is a Toucan, then the "real" 
            returned icon is replace with a copy of it having the ICON_TOUCAN iconid.
@return	    const SlotIcon*     - the icon for this gamemode, reel, and position
@param		uint8   gamemodeID  
@param		uint8   reelID
@param		uint8   position
********************************************************************************************************/
const SlotIcon* TripleToucanGuts::getIcon( uint8 gamemodeID, uint8 reelID, uint8 position ) const
{
    const SlotIcon* pRealIcon = super::getIcon( gamemodeID, reelID, position );

    // If we are in free spin mode and this reel has an active toucan substitution, then return 
    // our icon that looks like a toucan.
    if ( gamemodeID == MODE_FREE_SPIN
        && m_bAllowToucanIconSubstitutions
        && ICON_TOUCAN != pRealIcon->iconid 
		&& getToucanIconOnReel( reelID ) )
    {
        SlotIconSubstitutionMap::const_iterator substitute = m_mapSubstitutionIcons.find(pRealIcon);

        //If this is a stop than can be substituted with an Toucan,
        //return the duplicate Toucan icon.
        if( substitute != m_mapSubstitutionIcons.end() )
        {
            return substitute->second;
        }
    }
    return pRealIcon;
}



/********************************************************************************************************
@fn         TripleToucanGuts::getToucanLineWinResult
@brief	    Calculate the Toucan line win payout..
@return	    SpinResult      - A payout from the SpinResult enumeration.
@param		uint8* stops    - The array of stop positions for the line.
********************************************************************************************************/
TripleToucanGuts::SpinResult TripleToucanGuts::getToucanLineWinResult( uint8* stops ) const
{
	// Count how many Toucan we have at the beginning of the line.
	for ( uint8 i = 0; i < getReelCount(); i++ )
    {
		// If this icon is not a Toucan...
		if ( getIcon( getGameModeId(), i, stops[i] )->iconid != ICON_TOUCAN )
		{
			// then we have our total.
			break;
		}
    }

	// Use the array to look up the spin result for i Toucan.
	return lookupLineWinSpinResult( ICON_TOUCAN, i );
}



/********************************************************************************************************
@fn         TripleToucanGuts::getToucanIconOnReel
@brief	    Get a bool value that indicates if there is at least one toucan on the reel.
@return	    const bool8         - true if there is at least one toucan on the reel.
                                false if not.
@param		uint8   nReel       - Reel where the toucan is looked for.
********************************************************************************************************/
bool8 TripleToucanGuts::getToucanIconOnReel( uint8 nReel ) const
{
	if ( nReel == 0 || nReel == 2 || nReel == 4 )
	{
		int32 id = 0;
		switch ( nReel )
		{
		case 0:
			id = SGDIDX_TOUCAN_ICON_SUBST_REEL_1;
			break;
		case 2:
			id = SGDIDX_TOUCAN_ICON_SUBST_REEL_3;
			break;
		case 4:
			id = SGDIDX_TOUCAN_ICON_SUBST_REEL_5;
			break;
		}
		return 1 == m_subGame->getData( id );
	}

	return false;
}


/********************************************************************************************************
@fn         TripleToucanGuts::setToucanIconOnReel
@brief	    Set a bool value that indicates if there is at least one toucan on the reel.
@return	    void.
@param		uint8   nReel       - Reel where the toucan is looked for.
@param		bool8   substitute  - true if there is at least one toucan on the reel, false if not.
********************************************************************************************************/
void  TripleToucanGuts::setToucanIconOnReel( uint8 nReel, bool8 substitute )
{
	ASSERT( nReel == 0 || nReel == 2 || nReel == 4 );
	int32 id = 0;
	switch ( nReel )
	{
	case 0:
		id = SGDIDX_TOUCAN_ICON_SUBST_REEL_1;
		break;
	case 2:
		id = SGDIDX_TOUCAN_ICON_SUBST_REEL_3;
		break;
	case 4:
		id = SGDIDX_TOUCAN_ICON_SUBST_REEL_5;
		break;
	}

	m_subGame->update( id, substitute );
}


/********************************************************************************************************
@fn         TripleToucanGuts::clearToucanIconSubstitutions
@brief	    Clear the flag value that indicates if there is at least one toucan on the reel.
@return	    void.
@param		none.
********************************************************************************************************/
void  TripleToucanGuts::clearToucanIconSubstitutions()
{
	setToucanIconOnReel(0, false);
	setToucanIconOnReel(2, false);
	setToucanIconOnReel(4, false);
}


/********************************************************************************************************
@fn         TripleToucanGuts::preSpinClassifyResults
@brief	    Override the other stops on the reel with a toucan (if any of them is a toucan and if we are 
            in free spin mode) before classifying the results.
@return	    void.
@param		SlotSping*  spin    - Pointer to the spin with stop data.
********************************************************************************************************/
void TripleToucanGuts::preSpinClassifyResults( SlotSpin* spin )
{
	SlotGuts::preSpinClassifyResults(spin);

	// Once we've reached this point, we're certainly in a spin, and we
	// need to expose our toucan-icon if we are in free spin mode.
	m_bAllowToucanIconSubstitutions = true;
	
	clearToucanIconSubstitutions();	
		
	// If we are in free spin mode then we need to look at the stops to see if
	// any are toucan that will override the other stops.
	// Loop through all of the reels.
	int32 gamemode = getGameModeId();
    if(gamemode == MODE_FREE_SPIN) {
	    for ( uint8 reel = 0; reel < getReelCount(); reel++ )
	    {
		    for ( uint8 row = 0 ; row < 3 ; ++row )
		    {
			    // Get the current stop.
			    uint8 stop = relativeWheelPosition( gamemode, reel,
				    spin->getStops()[ reel ], row );
    			
			    int32 nIcon = super::getIcon( gamemode, reel, stop )->iconid;
    			
			    // If this has a toucan
			    if ( nIcon == ICON_TOUCAN )
			    {
				    setToucanIconOnReel( reel, true );
				    break;
			    }
		    }
	    }
    }
}


/********************************************************************************************************
@fn         TripleToucanGuts::getLineWinResultWithPossibleSubstitution
@brief	    Calculate the line win payout with a possible substitution.
@return	    cont SpinResult         - A payout from the SpinResult enumeration.
@param		uint8*  stops           - The array of stop positions for the line.
@param		uint8   testIcon        - The icon we are looking for, typically the first icon on the line.
@param		bool&   bSubstitution   - An output parameter that is set if a subsitution is used.
********************************************************************************************************/
TripleToucanGuts::SpinResult TripleToucanGuts::getLineWinResultWithPossibleSubstitution(
	uint8* stops, uint8 testIcon, bool& bSubstitution ) const
{
	// Initialize the out parameter
	bSubstitution = false;

	// Loop through the remaining reels until the streak is over
	for ( int i = 1; i < getReelCount(); i++ )
    {
		// See what this icon is.
		uint8 currentIcon = getIcon( getGameModeId(), i, stops[i] )->iconid;

		// If the current icon is a Toucan...
		if ( currentIcon == ICON_TOUCAN )
		{
			// then use it as a substitution symbol and continue on.
			bSubstitution = true;
			continue;
		}
		// Otherwise if the test icon is a Toucan...
		else if ( testIcon == ICON_TOUCAN )
		{
			// then we still have a substitution.  In this case the line
			// started out with the substitution symbol.
			bSubstitution = true;

			// We have now found our first icon that is not a substitution symbol.
			// All of the rest of the icons will have to match this one now for the
			// streak to continue, so change our test icon.
			testIcon = currentIcon;
			continue;
		}

		// If the current icon is not the test icon...
        if ( currentIcon != testIcon )
        {
			// then the streak is over so break out of the loop
			break;
        }
    }

	// If the test icon is still a Toucan...
	if ( testIcon == ICON_TOUCAN )
	{
		// then we must have 5 Toucan.
		ASSERT( i == 5 );

		// In this case we can't give them the substitution bonus.
		bSubstitution = false;
	}

	// Use the array to look up the spin result for i testIcons.
	return lookupLineWinSpinResult( testIcon, i );
}


/********************************************************************************************************
@fn         TripleToucanGuts::doesToucanLineWinPayMore
@brief	    Calculate which payout  the line win payout with a possible 
            substitution.
@return	    cont bool                   - True if the Toucan win is larger.
@param		SpinResult  srToucan        - The spin result to calculate the Toucan payout for.
@param		SpinResult  srOther         - The spin result to calculate the other payout for.
@param		bool        bSubstitution   - Set if we should use the substitution multiplier with the other 
                                        payout.
********************************************************************************************************/
bool TripleToucanGuts::doesToucanLineWinPayMore( SpinResult srToucan,
	SpinResult srOther, bool bSubstitution ) const
{
	// Lookup the payout for the Toucan line win.
	long nToucanLineWinPayout = getPayout( srToucan )->payoutAmount;

	// See what the total payout for the other line win is without the substitution
	// multiplier (if any).
	long nOtherLineWinPayout = getPayout( srOther )->payoutAmount;

	// If we had a substitution...
	if ( bSubstitution )
	{
		// then factor in the multiplier.
		nOtherLineWinPayout *= MULTIPLIER_SUBSTITUTION;
	}

	// Return true if the Toucan payout is bigger.
    return ( nToucanLineWinPayout > nOtherLineWinPayout );
}



/****************************************************************************************************
@fn         TripleToucanGuts::classifyStops
@brief	    Calculate the payout on a line.
@return	    void.
@param		SpinLine*   spinline
@param		uint8*      stops       - The array of stop positions for the line.
@param		uint8       bet         - The value of the line bet.
@param		uint8       line        - The index of the line.
@param		uint8&      rtnresult   - An output parameter that it set to the payout from the SpinResult 
                                    enumeration as a uint8.
@param		uint8&      multiplier  - An output parameter that it set to the multiplier that will be 
                                    used to calculate the line win payout.
****************************************************************************************************/
void TripleToucanGuts::classifyStops( SpinLine* spinline, uint8* stops, uint8 bet, uint8 line,
	uint8& rtnresult, uint8& multiplier )
{
	
    // Track the Toucan result separately since it might be changed to a substitution.
	SpinResult srToucanLineWinResult = getToucanLineWinResult( stops );
    
    // See what the payout is if we use any Toucan we find as substitution symbols.
	// Start with the icon on the first reel.
	uint8 testIcon = getIcon( getGameModeId(), 0, stops[0] )->iconid;

	// Declare a local variable to track whether or not we found a substitution.
	bool bSubstitution = false;

	// See what the spin result is if we used any Toucan as substitution symbols.
	SpinResult srResultWithPossibleSubstitution =	getLineWinResultWithPossibleSubstitution( stops, testIcon, bSubstitution );


    // Use the larger payout between the regular Toucan evaluation compared to
	// the evaluation with the possible Toucan substitution.
    if ( doesToucanLineWinPayMore( srToucanLineWinResult,
		srResultWithPossibleSubstitution, bSubstitution ) )
	{
		// The Toucan by themselves pay out more so use the Toucan result.
		rtnresult = srToucanLineWinResult;
	}
	else
	{
		// Otherwise the result with the substitution (if any) paid more so use it.
		rtnresult = srResultWithPossibleSubstitution;

		// If we did actually have a substitution and a winning spin...
		if ( bSubstitution && srResultWithPossibleSubstitution != EVT_LOSER )
		{
			// then add a note and change the multiplier.
			spinline->addNote( NOTE_SUBSTITUTION );
			multiplier = MULTIPLIER_SUBSTITUTION;
		}
	}
}


/****************************************************************************************************
@fn         TripleToucanGuts::tryForJackpot
@brief	    Look to see if we hit the jackpot.
@return	    void.
@param		SlotSpin* spin      - Pointer to the spin with stop data.
****************************************************************************************************/
void TripleToucanGuts::tryForJackpot( SlotSpin* spin )
{
	// If we are in the first paid spin (NOT a bonus spin)...
	if ( getGameModeId() == MODE_NORMAL ) 
	{
		// then try for the Random Progressive Jackpot
		// If we hit the jackpot...
		if ( getRandomProgressiveJackpotResult( getNumLinesBet() ) || 
             m_bForceRandomJackpot == true )
		{
			// then add a jackpot scatter to the spin.
			spin->addScatter( 0,
				getPayout( EVT_RANDOM_PROGRESSIVE_WINNER )->payoutAmount, 1,
				true, EVT_RANDOM_PROGRESSIVE_WINNER, 0 );
		}
    }
}


/****************************************************************************************************
@fn         TripleToucanGuts::getScatterWinResult
@brief	    Evaluate the spin for scatters.
@return	    const SpinResult.               - A payout from the SpinResult enumeration.
@param		SlotSpin*   spin                - The current spin object.
@param		int32&      nNumScatterIcons    - An output parameter that it set to the number of scatter 
                                            icons that we find.
@param		int32&      nScatterPositions   - An output parameter that it set to the bit mask for 
                                            the scatters positions that we find.
****************************************************************************************************/
TripleToucanGuts::SpinResult TripleToucanGuts::getScatterWinResult( SlotSpin* spin, int32& nNumScatterIcons, int32& nScatterPositions) const
{
	// Initialize the scatterPositions.
	nScatterPositions = 0;

	// Loop through each reel.
  	for( int reel = 0; reel < getReelCount(); reel++ )
	{
		// The position bit for the current icon in case it needs to be stored in a mask.
		uint8 position = reel;

		// Loop through each row in the wheel house.
		for( int row = 0; row < 3; row++ )
		{
			// Get the current stop.
			uint8 stop = relativeWheelPosition( getGameModeId(), reel,
				spin->getStops()[ reel ], row );

			// Get the icon for the current stop.
			uint8 currentIcon = getIcon( getGameModeId(), reel, stop )->iconid;
			
			// If the icon is the one we are looking for...
			if ( currentIcon == ICON_FRUITS )
			{
				// then increase the icon count
				nNumScatterIcons++;

				// Set the bit in the position mask for this stop.
				nScatterPositions |= 1 << position;
			}

			// Move to the next bit in the position mask.
            position += 5;
		}
	}

	// Use the array to look up the spin result for nNumScatterIcons.
	return lookupScatterWinSpinResult( nNumScatterIcons );
}


/****************************************************************************************************
@fn         TripleToucanGuts::addScatterWin
@brief	    Determine if the current spin wins a scatter payment and adds the scatter.
@return	    void
@param		SlotSpin*   spin                - The current spin object.
@param		SpinResult  srScatterResult     - Payout from the scatter SpinResult enumeration.
@param		int32      nScatterPositions    - Bit mask for the scatters positions that we find.
****************************************************************************************************/
void TripleToucanGuts::addScatterWin( SlotSpin* spin, SpinResult srScatterResult, int32 nScatterPositions )
{
    // If we got the scatter win (or almost got it)
	if ( srScatterResult != EVT_LOSER )
	{
		// Get the base payout for the scatter.
		int32 nPayout = getPayout( srScatterResult )->payoutAmount;
		
		// Scatters payout based on the total bet, so factor in the number of bet lines.
		nPayout *= spin->getSpinLineCount();

		// Default to no multiplier.
		int32 nMultiplier = 1;

		// Add the payout to the total win for this spin.
		increaseTotalWin( nPayout * nMultiplier );
    
		// Add a scatter to the spin.
		spin->addScatter( nScatterPositions,
			nPayout * getBetPerLine(), nMultiplier, false, srScatterResult, 0 );
	}
}

//////////////////////////////////////////////////////////////////////////////
///// @fn 	 TripleToucanGuts::addFeatureTrigger()
/////
///// This function determines if the current spin triggered the free game
///// feature and adds the appropriate scatter.
//////////////////////////////////////////////////////////////////////////////
void TripleToucanGuts::addFeatureTrigger( SlotSpin* spin, int32& nNumScatterIcons, int32 nFeatureScatterPositions )
{
	// We need a place to keep up with how many free spins to award.
	int32 nFreeSpins = 0;

	// Also keep up with what type of feature trigger it is.
	SpinResult srFeatureResult = EVT_LOSER;

	// Figure out how many free spins they get.
	if ( nNumScatterIcons == 1 )
	{
		srFeatureResult = EVT_FEATURE_NEAR_MISS;
	}
	else if ( nNumScatterIcons == 2 )
	{
		srFeatureResult = EVT_FEATURE_NEAR_MISS;
	}
	else if ( nNumScatterIcons == 3 )
	{
		nFreeSpins = 9;
		srFeatureResult = EVT_FREE_GAME_FEATURE;
	}
	else if ( nNumScatterIcons == 4 )
	{
		nFreeSpins = 15;
		srFeatureResult = EVT_FREE_GAME_FEATURE;
	}
	else if ( nNumScatterIcons == 5 )
	{
		nFreeSpins = 25;
		srFeatureResult = EVT_FREE_GAME_FEATURE;
	}

	// If they get free spins...
	if ( nFreeSpins )
	{
		// then change the game mode.
		setGameModeId( MODE_FREE_SPIN );

		// Add the free spins.
		incrementFreeSpins( nFreeSpins );
	}

	// If we had a trigger or a near miss...
	if ( srFeatureResult != EVT_LOSER )
	{
		// then add a scatter to the spin for the feature trigger.
		spin->addScatter( nFeatureScatterPositions, 0, 0, false,
			srFeatureResult, nFreeSpins );
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 TripleToucanGuts::classifyScatters( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This is an override of the framework method.  
/// It determines if the current spin merits free spins or scatter payments.
////////////////////////////////////////////////////////////////////////////
void TripleToucanGuts::classifyScatters( SlotSpin* spin )
{	
	// Try for the Random Progressive Jackpot
	tryForJackpot( spin );

	// Declare some local variables to track the scatter positions.
	int32 nScatterPositions = 0;
	int32 nNumScatterIcons = 0;

	// See if there is a scatter win.
	SpinResult srResult = getScatterWinResult( spin, nNumScatterIcons, nScatterPositions);

	// Add the scatter, if any.
	addScatterWin( spin, srResult, nScatterPositions);

	// Add the scatters for the free game feature or near miss.
	addFeatureTrigger( spin, nNumScatterIcons, nScatterPositions );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 TripleToucanGuts::isValidGuts()   
///
/// @return	 bool8      True if gut is valid.    
///
/// This helper method is used to see if the current gut ID is valid.
////////////////////////////////////////////////////////////////////////////
bool8 TripleToucanGuts::isValidGuts()
{
	// Make sure that the m_aLineWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 icons on the line.
	// Note:  we can't do this in the constructor because we have to call
	// getReelCount.
	ASSERT( countof( m_aLineWinSpinResults[0] ) == getReelCount( MODE_NORMAL ) + 1 );

	// Make sure that the m_aScatterWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 icons on the line.
	ASSERT( countof( m_aScatterWinSpinResults ) == getReelCount( MODE_NORMAL ) + 1 );

	// Now make sure that all game modes have the same number of reels.
	ASSERT( getReelCount( MODE_NORMAL ) == getReelCount( MODE_FREE_SPIN ) );

	// Finally just check to see if the gut is within the right range.
    return ( getGutsId() >= 2100 && getGutsId() < 2200 );
}


////////////////////////////////////////////////////////////////////////////
/// @fn 	 TripleToucanGuts::Debug_SetLoserStops( uint8* pStops )
///
/// @param   pStops		The stops to set.
///
/// Base class override, returns a losing spin triggered by the debug tool
////////////////////////////////////////////////////////////////////////////
void TripleToucanGuts::Debug_SetLoserStops( uint8* pStops )
{
	pStops[0]=0;
	pStops[1]=0;
	pStops[2]=0;
	pStops[3]=0;
	pStops[4]=0;
}
